﻿using UnityEngine;
using System.Collections;
using NCmd;
using System;
using System.Collections.Generic;

// 生命体的当前状态
public enum CreatureState
{
    Idle = 0,
    Run = 1,
    Die = 2,
    Respawn = 3,
}


// 生命体，Npc和角色的父类
public class Creature : MonoBehaviour
{
    public AddSceneCreature ServerData;
    public CreatureTableData TableData;

    // 当前的注视目标
    public Creature CurTarget;

    // 当前的状态
    private CreatureState _state = CreatureState.Idle;
    public CreatureState State
    {
        private set
        {
            _state = value;
            //if (this == RoleMgr.Instance.MainRole)
            //{ Debug.Log(_state); }
        }
        get { return _state; }
    }

    // 当血量改变的时候通知<oldValue, newValue, maxValue>
    public event Action<int, int, int> HpChangeCallback;

    // 角色带有目的(有目的性的寻路移动)
    private Purpose realP;
    protected Purpose _curPurpose
    {
        set {
            realP = value; }
        get { return realP; }
    }

    protected NavMeshAgent _agent;
    protected Animator _ani;

    // 技能管理器
    protected SkillMgr _skillMgr = new SkillMgr();

    // 当前的位置
    public Vector3 Position
    {
        get { return transform.position; }
        set { transform.position = value; }
    }

    // 血量
    public int HP
    {
        get { return ServerData.HP; }
        set
        {
            int oldValue = ServerData.HP;
            ServerData.HP = Mathf.Max(value, 0);
            // 通知外界
            if (oldValue != ServerData.HP)
            {
                if (HpChangeCallback != null)
                {
                    HpChangeCallback(oldValue, ServerData.HP, ServerData.MaxHP);
                }
            }

            // 死亡
            if (oldValue > 0 && ServerData.HP <= 0)
            {
                onDie();
            }

            // 重生
            if (oldValue <= 0 && ServerData.HP > 0)
            {
                onRespawn();
            }
        }
    }

    // 重生
    protected virtual void onRespawn()
    {
        State = CreatureState.Idle;
        SetAnimationID((int)CreatureState.Respawn);
    }

    // 死亡
    protected virtual void onDie()
    {
        State = CreatureState.Die;
        SetAnimationID((int)State);

        var timer = TimerMgr.Instance.CreateTimer(2, 1, respawn);
        timer.Start();
    }

    // 假重生
    private void respawn()
    {
        HP = ServerData.MaxHP;
    }

    // 是否能移动
    public bool CanMove { get
        {
            return !IsCastingSkill && IsAlive;
        }
    }

    // 是否存活
    public bool IsAlive
    {
        get { return State != CreatureState.Die; }
    }

    public bool IsCastingSkill
    {
        get { return _skillMgr.IsCastingSkill; }
    }

    public bool CanCastSkill
    {
        get { return IsAlive; }
    }

    protected float GetLeftCD(int index)
    {
        return _skillMgr.GetLeftCD(index);
    }
    protected float GetMaxCD(int index)
    {
        return _skillMgr.GetMaxCD(index);
    }

    public virtual void Init(AddSceneCreature serverData, CreatureTableData tableData)
    {
        ServerData = serverData;
        TableData = tableData;

        State = CreatureState.Idle;

        _ani = GetComponent<Animator>();

        // 处理位置属性
        gameObject.transform.position = serverData.Pos;
        gameObject.transform.rotation = Quaternion.Euler(serverData.FaceTo);

        _agent = gameObject.AddComponent<NavMeshAgent>();
        _agent.speed = 5;
        _agent.angularSpeed = float.MaxValue;
        _agent.acceleration = float.MaxValue;
        _agent.obstacleAvoidanceType = ObstacleAvoidanceType.NoObstacleAvoidance;

        _skillMgr.Init(this);
    }

    // 施放技能。index，技能逻辑索引号
    public void CastSkill(int indexLogic)
    {
        if (!CanCastSkill)
        {
            return;
        }

        _skillMgr.CastSkill(indexLogic);
    }

    // 我能不能被attacker攻击
    public virtual bool CanBeAttack(Creature attacker)
    {
        if (attacker == this)
        {
            return false;
        }

        return IsAlive;
    }

    // Update is called once per frame
    protected virtual void Update()
    {
        loopSkill();

        // 要检测目标是否达成，若达成则提前终止移动，通知外界do something
        if (_curPurpose != null)
        {
            _curPurpose.Loop();

            if (_agent.hasPath
                && _agent.remainingDistance <= _curPurpose.StopDis
                && !_agent.pathPending)
            {
                // 达成目标，提前终止
                MoveStop();
                doPurpos();
            }

            return;
        }

        // 正常停止
        if (State == CreatureState.Run && 
            !_agent.hasPath
            && _agent.remainingDistance <= _agent.stoppingDistance
            && !_agent.pathPending)
        {
            MoveStop();
        }
    }

    // 驱动技能
    private void loopSkill()
    {
        _skillMgr.Loop();
    }

    private void doPurpos()
    {
        if (_curPurpose != null && _curPurpose.OnReachTarget != null)
        {
            var callback = _curPurpose.OnReachTarget;
            _curPurpose = null;
            callback();
        }
    }

    // 寻路移动到target点
    private void pathMoveTo(Vector3 target)
    {
        _agent.Resume();

        _agent.SetDestination(target);

        State = CreatureState.Run;
        SetAnimationID((int)State);
    }

    // 带有目的性的移动到某个点
    // stopDis == -1,表示跑向某个点
    public void PurposeTo(Vector3 target, float stopDis = -1, Action onReachCallback = null)
    {
        _curPurpose = null;

        // 当前是否能够移动
        if (!CanMove)
        {
            return;
        }

        if (stopDis < 0)
        {
            pathMoveTo(target);
            return;
        }

        if (Vector3.Distance(transform.position, target) <= stopDis)
        {
            if (onReachCallback != null) { onReachCallback(); }
            MoveStop();
            return;
        }

        _curPurpose = new Purpose();
        _curPurpose.Target = target;
        _curPurpose.StopDis = stopDis;
        _curPurpose.OnReachTarget = onReachCallback;

        pathMoveTo(target);
    }

    public void TraceTo(Creature target, float stopDis = -1, Action onReachCallback = null)
    {
        _curPurpose = null;

        if (target == null) { return; }

        // 当前是否能够移动
        if (!CanMove)
        {
            return;
        }

        if (stopDis < 0)
        {
            stopDis = _agent.stoppingDistance;
        }

        var curTrace = new TracePurpose();
        curTrace.TraceTarget = target;
        curTrace.StopDis = stopDis;
        curTrace.OnReachTarget = onReachCallback;
        curTrace.TraceLoopCallback = pathMoveTo;

        _curPurpose = curTrace;

        pathMoveTo(curTrace.TraceTarget.Position);
    }

    public void SetAnimationID(int id)
    {
        _ani.SetInteger("MotionType", id);
    }

    public int GetAnimationID()
    {
        return _ani.GetInteger("MotionType");
    }

    public void MoveStop()
    {
        if (State == CreatureState.Run)
        {
            State = CreatureState.Idle;
            SetAnimationID((int)State);
        }

        _agent.Stop();
        _agent.ResetPath();
    }


    // 不带Y轴的lookat
    public void LookAt2D(Vector3 position)
    {
        var target = new Vector3(position.x, transform.position.y, position.z);
        transform.LookAt(target);
    }

    public void LookAt2D(Creature target)
    {
        LookAt2D(target.transform.position);
    }

}
